// UIImage+Resize.m
// Created by Trevor Harmon on 8/5/09.
// Free for personal or commercial use, with or without modification.
// No warranty is expressed or implied.

#import "UIImage+Resize.h"
#import "UIImage+RoundedCorner.h"
#import "UIImage+Alpha.h"

#define MediumMaxSize 1334
#define MediumMinSize 750
#define RawMaxSize 2000



// Private helper methods
@interface UIImage (ResizePrivateMethods)
- (UIImage *)resizedImage:(CGSize)newSize
                transform:(CGAffineTransform)transform
           drawTransposed:(BOOL)transpose
     interpolationQuality:(CGInterpolationQuality)quality;
- (CGAffineTransform)transformForOrientation:(CGSize)newSize;
@end

@implementation UIImage (Resize)

// Returns a copy of this image that is cropped to the given bounds.
// The bounds will be adjusted using CGRectIntegral.
// This method ignores the image's imageOrientation setting.
- (UIImage *)croppedImage:(CGRect)bounds {
    CGImageRef imageRef = CGImageCreateWithImageInRect([self CGImage], bounds);
    UIImage *croppedImage = [UIImage imageWithCGImage:imageRef];
    CGImageRelease(imageRef);
    return croppedImage;
}

// Returns a copy of this image that is squared to the thumbnail size.
// If transparentBorder is non-zero, a transparent border of the given size will be added around the edges of the thumbnail. (Adding a transparent border of at least one pixel in size has the side-effect of antialiasing the edges of the image when rotating it using Core Animation.)
- (UIImage *)thumbnailImage:(NSInteger)thumbnailSize
          transparentBorder:(NSUInteger)borderSize
               cornerRadius:(NSUInteger)cornerRadius
       interpolationQuality:(CGInterpolationQuality)quality {
    UIImage *resizedImage = [self resizedImageWithContentMode:UIViewContentModeScaleAspectFill
                                                       bounds:CGSizeMake(thumbnailSize, thumbnailSize)
                                         interpolationQuality:quality];
    
    // Crop out any part of the image that's larger than the thumbnail size
    // The cropped rect must be centered on the resized image
    // Round the origin points so that the size isn't altered when CGRectIntegral is later invoked
    CGRect cropRect = CGRectMake(round((resizedImage.size.width - thumbnailSize) / 2),
                                 round((resizedImage.size.height - thumbnailSize) / 2),
                                 thumbnailSize,
                                 thumbnailSize);
    UIImage *croppedImage = [resizedImage croppedImage:cropRect];
    
    UIImage *transparentBorderImage = borderSize ? [croppedImage transparentBorderImage:borderSize] : croppedImage;

    return [transparentBorderImage roundedCornerImage:cornerRadius borderSize:borderSize];
}

-(UIImage*)getThumbImageForOther {
    return [self thumbnailImage:LENGTH_BASIC*3 transparentBorder:0 cornerRadius:0 interpolationQuality:kCGInterpolationHigh];
}


// Returns a rescaled copy of the image, taking into account its orientation
// The image will be scaled disproportionately if necessary to fit the bounds specified by the parameter
- (UIImage *)resizedImage:(CGSize)newSize interpolationQuality:(CGInterpolationQuality)quality {
    BOOL drawTransposed;
    
    switch (self.imageOrientation) {
        case UIImageOrientationLeft:
        case UIImageOrientationLeftMirrored:
        case UIImageOrientationRight:
        case UIImageOrientationRightMirrored:
            drawTransposed = YES;
            break;
            
        default:
            drawTransposed = NO;
    }
    
    return [self resizedImage:newSize
                    transform:[self transformForOrientation:newSize]
               drawTransposed:drawTransposed
         interpolationQuality:quality];
}

// Resizes the image according to the given content mode, taking into account the image's orientation
- (UIImage *)resizedImageWithContentMode:(UIViewContentMode)contentMode
                                  bounds:(CGSize)bounds
                    interpolationQuality:(CGInterpolationQuality)quality {
    CGFloat horizontalRatio = bounds.width / self.size.width;
    CGFloat verticalRatio = bounds.height / self.size.height;
    CGFloat ratio;
    
    switch (contentMode) {
        case UIViewContentModeScaleAspectFill:
            ratio = MAX(horizontalRatio, verticalRatio);
            break;
            
        case UIViewContentModeScaleAspectFit:
            ratio = MIN(horizontalRatio, verticalRatio);
            break;
            
        default:
            [NSException raise:NSInvalidArgumentException format:@"Unsupported content mode: %@", @(contentMode)];
    }
    
    CGSize newSize = CGSizeMake(round(self.size.width * ratio), round(self.size.height * ratio));
    
    return [self resizedImage:newSize interpolationQuality:quality];
}

#pragma mark -
#pragma mark Private helper methods

// Returns a copy of the image that has been transformed using the given affine transform and scaled to the new size
// The new image's orientation will be UIImageOrientationUp, regardless of the current image's orientation
// If the new size is not integral, it will be rounded up
- (UIImage *)resizedImage:(CGSize)newSize
                transform:(CGAffineTransform)transform
           drawTransposed:(BOOL)transpose
     interpolationQuality:(CGInterpolationQuality)quality {
    CGRect newRect = CGRectIntegral(CGRectMake(0, 0, newSize.width, newSize.height));
    CGRect transposedRect = CGRectMake(0, 0, newRect.size.height, newRect.size.width);
    CGImageRef imageRef = self.CGImage;
    
    // Build a context that's the same dimensions as the new size
	CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
	if((bitmapInfo == kCGImageAlphaLast) || (bitmapInfo == kCGImageAlphaNone))
		bitmapInfo = kCGImageAlphaNoneSkipLast;
		
    CGContextRef bitmap = CGBitmapContextCreate(NULL,
                                                newRect.size.width,
                                                newRect.size.height,
                                                CGImageGetBitsPerComponent(imageRef),
                                                0,
                                                CGImageGetColorSpace(imageRef),
                                                bitmapInfo);
    
    // Rotate and/or flip the image if required by its orientation
    CGContextConcatCTM(bitmap, transform);
    
    // Set the quality level to use when rescaling
    CGContextSetInterpolationQuality(bitmap, quality);
    
    // Draw into the context; this scales the image
    CGContextDrawImage(bitmap, transpose ? transposedRect : newRect, imageRef);
    
    // Get the resized image from the context and a UIImage
    CGImageRef newImageRef = CGBitmapContextCreateImage(bitmap);
    UIImage *newImage = [UIImage imageWithCGImage:newImageRef];
    
    // Clean up
    CGContextRelease(bitmap);
    CGImageRelease(newImageRef);
    
    return newImage;
}

// Returns an affine transform that takes into account the image orientation when drawing a scaled image
- (CGAffineTransform)transformForOrientation:(CGSize)newSize {
    CGAffineTransform transform = CGAffineTransformIdentity;
    
    switch (self.imageOrientation) {
        case UIImageOrientationDown:           // EXIF = 3
        case UIImageOrientationDownMirrored:   // EXIF = 4
            transform = CGAffineTransformTranslate(transform, newSize.width, newSize.height);
            transform = CGAffineTransformRotate(transform, M_PI);
            break;
            
        case UIImageOrientationLeft:           // EXIF = 6
        case UIImageOrientationLeftMirrored:   // EXIF = 5
            transform = CGAffineTransformTranslate(transform, newSize.width, 0);
            transform = CGAffineTransformRotate(transform, M_PI_2);
            break;
            
        case UIImageOrientationRight:          // EXIF = 8
        case UIImageOrientationRightMirrored:  // EXIF = 7
            transform = CGAffineTransformTranslate(transform, 0, newSize.height);
            transform = CGAffineTransformRotate(transform, -M_PI_2);
            break;

        default:
            break;
    }
    
    switch (self.imageOrientation) {
        case UIImageOrientationUpMirrored:     // EXIF = 2
        case UIImageOrientationDownMirrored:   // EXIF = 4
            transform = CGAffineTransformTranslate(transform, newSize.width, 0);
            transform = CGAffineTransformScale(transform, -1, 1);
            break;
            
        case UIImageOrientationLeftMirrored:   // EXIF = 5
        case UIImageOrientationRightMirrored:  // EXIF = 7
            transform = CGAffineTransformTranslate(transform, newSize.height, 0);
            transform = CGAffineTransformScale(transform, -1, 1);
            break;
            
        default:
            break;
    }
    
    return transform;
}


-(UIImage*)getThumbImageForMessage{
    return [self getThumbImagePrivate:MIN_BUBBLE_LENGTH max:MAX_BUBBLE_LENGTH super:SUPER_BUBBLE_LENGTH];
}

-(UIImage*)getThumbImageForCircle{
    return [self getThumbImagePrivate:MIN_BUBBLE_LENGTH_CIRCLE max:MAX_BUBBLE_LENGTH_CIRCLE super:MAX_BUBBLE_LENGTH_CIRCLE];
}


-(UIImage*)getThumbImagePrivate:(CGFloat)min max:(CGFloat)max super:(CGFloat)superLen{
    CGSize originSize=self.size;
    CGSize tempImageSize;
    UIImage *image=nil;
    CGRect rect;
    //判断是否是超高或超宽图
    if(originSize.height / originSize.width >= 3){
        //超高图
        CGFloat scale=min/originSize.width;
        tempImageSize.width=min;
        tempImageSize.height=originSize.height*scale;
        image=[self scaleToSize:tempImageSize];
        if(tempImageSize.height >= superLen){
            tempImageSize.height=superLen;
        }
        CGRect rect=CGRectMake(0, 0, tempImageSize.width, tempImageSize.height);
        image=[UIImage imageWithCGImage:CGImageCreateWithImageInRect(image.CGImage,rect)];
        
    }else if(originSize.width / originSize.height >= 3){
        //超宽图
        CGFloat scale=min/originSize.height;
        tempImageSize.height=min;
        tempImageSize.width=originSize.width*scale;
        image=[self scaleToSize:tempImageSize];
        if(tempImageSize.width >= superLen){
            tempImageSize.width=superLen;
        }
        rect=CGRectMake(0, 0, tempImageSize.width, tempImageSize.height);
        image=[UIImage imageWithCGImage:CGImageCreateWithImageInRect(image.CGImage,rect)];
    }else{
        
        //宽大一些
        if(originSize.width >= originSize.height){
            CGFloat scale=max/originSize.width;
            tempImageSize.width=max;
            tempImageSize.height=originSize.height*scale;
            image=[self scaleToSize:tempImageSize];
            if(tempImageSize.height < min){
                scale=min/tempImageSize.height;
                tempImageSize.height=min;
                tempImageSize.width=tempImageSize.width*scale;
                image=[self scaleToSize:tempImageSize];
                if(tempImageSize.width >= max)
                    tempImageSize.width=max;
            }
            rect=CGRectMake(0, 0, tempImageSize.width, tempImageSize.height);
            image=[UIImage imageWithCGImage:CGImageCreateWithImageInRect(image.CGImage,rect)];
            
        }else{
            CGFloat scale=max/originSize.height;
            tempImageSize.height=max;
            tempImageSize.width=originSize.width*scale;
            image=[self scaleToSize:tempImageSize];
            if(tempImageSize.width < min){
                scale=min/tempImageSize.width;
                tempImageSize.width=min;
                tempImageSize.height *= scale;
                image=[self scaleToSize:tempImageSize];
                if(tempImageSize.height >= max)
                    tempImageSize.height=max;
            }
            rect=CGRectMake(0, 0, tempImageSize.width, tempImageSize.height);
            image=[UIImage imageWithCGImage:CGImageCreateWithImageInRect(image.CGImage,rect)];
        }
    }
    return image;
}




-(UIImage*)getThumbImageBySize:(CGSize)size isGetTopOrLeftForLongImage:(BOOL)longImage maxLength:(NSInteger)maxLength{
    CGSize thumbSize=size;
    CGSize originSize=self.size;
    CGSize tempImageSize;
    UIImage *image=nil;
    CGRect rect;
    
    //    //如果需要的截尺寸图比原图还大，则返回原图
    //    if(thumbSize.height>=originSize.height && thumbSize.width >= originSize.width)
    //        return self;
    
    if(longImage){
        //判断是否是超高或超宽图
        if(originSize.height / originSize.width >= 3){
            //超高图
            CGFloat scale=thumbSize.width/originSize.width;
            tempImageSize.width=thumbSize.width;
            tempImageSize.height=originSize.height*scale;
            image=[self scaleToSize:tempImageSize];
            if (tempImageSize.height >= thumbSize.height) {
                tempImageSize.height=thumbSize.height;
            }
            rect=CGRectMake(0, 0, thumbSize.width, thumbSize.height);
            image=[UIImage imageWithCGImage:CGImageCreateWithImageInRect(image.CGImage,rect)];
        }else if(originSize.width / originSize.height >= 3){
            //超宽图
            CGFloat scale=thumbSize.height/originSize.height;
            tempImageSize.height=thumbSize.height;
            tempImageSize.width=originSize.width*scale;
            image=[self scaleToSize:tempImageSize];
            if(tempImageSize.width >= thumbSize.width){
                tempImageSize.width=thumbSize.width;
            }
            rect=CGRectMake(0, 0, thumbSize.width, thumbSize.height);
            image=[UIImage imageWithCGImage:CGImageCreateWithImageInRect(image.CGImage,rect)];
        }else{
            image=[self getCenterImage:originSize thumbSize:thumbSize];
        }
    }else{
        image=[self getCenterImage:originSize thumbSize:thumbSize];
    }
    
    //反复压缩保证不能超过指定的字节
    NSData *imageData=UIImageJPEGRepresentation(image,1);
    NSInteger length=imageData.length/1024;
    float compressionQuality=1;
    while (length > maxLength && compressionQuality > 0.1) {
        compressionQuality -= 0.1;
        imageData=UIImageJPEGRepresentation(image,compressionQuality);
        length=imageData.length/1024;
    }
    image = [UIImage imageWithData:imageData];
    NSLog(@"%lukB",(unsigned long)imageData.length/1024);
    return image;

}

-(UIImage*)getCenterImage:(CGSize)originSize thumbSize:(CGSize)thumbSize{
    CGSize tempImageSize;
    UIImage *image=nil;
    //参照高的比例压缩图片
    if(originSize.width >= originSize.height){
        CGFloat scale=thumbSize.height/originSize.height;
        tempImageSize.height=thumbSize.height;
        tempImageSize.width=originSize.width*scale;
    }else{
        CGFloat scale=thumbSize.width/originSize.width;
        tempImageSize.width=thumbSize.width;
        tempImageSize.height=originSize.height*scale;
    }
    //原图的放大、缩小图，高宽比不变
    //    image = [self resizedImage:tempImageSize interpolationQuality:kCGInterpolationHigh];
    image = [self scaleToSize:tempImageSize];
    CGPoint point;
    if(originSize.height > originSize.width){
        point.y=( tempImageSize.height - thumbSize.height)*0.5;
        point.x=0;
    }else{
        point.x=( tempImageSize.width - thumbSize.width)*0.5;
        point.y=0;
    }
    CGRect rect=CGRectMake((int)point.x, (int)point.y, thumbSize.width, thumbSize.height);
    image=[UIImage imageWithCGImage:CGImageCreateWithImageInRect(image.CGImage,rect)];
    
    return image;
}

-(UIImage*)scaleToSize:(CGSize)size
{
    // 创建一个bitmap的context
    // 并把它设置成为当前正在使用的context
    UIGraphicsBeginImageContext(size);
    // 绘制改变大小的图片
    [self drawInRect:CGRectMake(0, 0, size.width, size.height)];
    // 从当前context中创建一个改变大小后的图片
    UIImage* scaledImage = UIGraphicsGetImageFromCurrentImageContext();
    // 使当前的context出堆栈
    UIGraphicsEndImageContext();
    // 返回新的改变大小后的图片
    return scaledImage;
}


-(UIImage*)getMediumImage{
    UIImage *image=nil;
    if(self.size.height <= MediumMaxSize && self.size.width <= MediumMaxSize){
        return self;
    }else{
        CGSize tempImageSize;
        //参照高的比例压缩图片
        if(self.size.width >= self.size.height && self.size.height >= MediumMinSize){
            CGFloat scale=MediumMinSize/self.size.height;
            tempImageSize.height=self.size.height*scale;
            tempImageSize.width=self.size.width*scale;
        }else if(self.size.width < self.size.height && self.size.width >= MediumMinSize){
            CGFloat scale=MediumMinSize/self.size.width;
            tempImageSize.width=self.size.width*scale;
            tempImageSize.height=self.size.height*scale;
        }else{
            tempImageSize = CGSizeMake(self.size.width/2, self.size.height/2);
        }
        image=[self scaleToSize:tempImageSize];
    }
    return image;
}


-(NSData*)getMediumImageData{
    UIImage *img = [self getMediumImage];
    
    CGFloat compression = 0.8f;
    CGFloat maxCompression = 0.1f;
    int maxFileSize = 700*1024;
    
    NSData *imageData = UIImageJPEGRepresentation(img, compression);
    
    while ([imageData length] > maxFileSize && compression > maxCompression){
        compression -= 0.2;
        imageData = UIImageJPEGRepresentation(img, compression);
        img = [UIImage imageWithData:imageData];
    }
    
    return imageData;
}

-(NSData*)getRawImageData{
    CGSize tempImageSize;
    UIImage *img=self;
    if(self.size.width > RawMaxSize || self.size.height > RawMaxSize){
        if(self.size.width >= self.size.height && self.size.height >= RawMaxSize){
            CGFloat scale=RawMaxSize/self.size.height;
            tempImageSize.height=self.size.height*scale;
            tempImageSize.width=self.size.width*scale;
        }else if(self.size.width < self.size.height && self.size.width >= RawMaxSize){
            CGFloat scale=RawMaxSize/self.size.width;
            tempImageSize.width=self.size.width*scale;
            tempImageSize.height=self.size.height*scale;
        }else{
            tempImageSize = CGSizeMake(self.size.width/2, self.size.height/2);
        }
        img=[self scaleToSize:tempImageSize];
    }
    
    CGFloat compression = 0.8f;
    CGFloat maxCompression = 0.1f;
    int maxFileSize = 3*1024*1024;
    NSData *imageData = UIImageJPEGRepresentation(img, compression);
    while ([imageData length] > maxFileSize && compression > maxCompression){
        compression -= 0.2;
        imageData = UIImageJPEGRepresentation(img, compression);
        img = [UIImage imageWithData:imageData];
    }
    return imageData;
}




- (UIImage *)adaptToSize:(CGSize)size {
    
    //获取屏幕的像素密度
    CGFloat scale = [[UIScreen mainScreen] scale];
    // 创建一个bitmap的context
    // 并把它设置成为当前正在使用的context
    UIGraphicsBeginImageContextWithOptions(size, NO, scale);

    // 绘制改变大小的图片
    [self drawInRect:CGRectMake(0, 0, size.width, size.height)];
    // 从当前context中创建一个改变大小后的图片
    UIImage* scaledImage = UIGraphicsGetImageFromCurrentImageContext();
    // 使当前的context出堆栈
    UIGraphicsEndImageContext();
    
    // 返回新的改变大小后的图片
    return scaledImage;
}

@end
